﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using System.Xml;
using System.Linq;
using Microsoft.AspNetCore.Http;
using System.Threading; // 多线程安全需引入

namespace XuanXiang.Infrastructure.Tools
{
    public class LatLng
    {
        public LatLng(double x, double y)
        {
            latitude = x;
            longitude = y;
        }
        public double latitude;
        public double longitude;
    }

    /// <summary>
    /// 配置文件操作类 + 订单ID生成工具
    /// </summary>
    public class Config
    {
        // 订单ID生成：每日流水号（线程安全）
        private static int _orderDailyCounter = 1;
        private static DateTime _orderLastResetTime = DateTime.Today;

        private readonly static Random rd = new();
        private const double EARTH_RADIUS = 6378137;

        /// <summary>
        /// 计算两点位置的距离，返回两点的距离，单位 米
        /// 该公式为GOOGLE提供，误差小于0.2米
        /// </summary>
        /// <param name="lat1">第一点纬度</param>
        /// <param name="lng1">第一点经度</param>
        /// <param name="lat2">第二点纬度</param>
        /// <param name="lng2">第二点经度</param>
        /// <returns></returns>
        public static double GetDistance(double lat1, double lng1, double lat2, double lng2)
        {
            double radLat1 = Rad(lat1);
            double radLng1 = Rad(lng1);
            double radLat2 = Rad(lat2);
            double radLng2 = Rad(lng2);
            double a = radLat1 - radLat2;
            double b = radLng1 - radLng2;
            double result = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2))) * EARTH_RADIUS;
            return result;
        }

        /// <summary>
        /// 经纬度转化成弧度
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        private static double Rad(double d)
        {
            return (double)d * Math.PI / 180d;
        }

        /// <summary>
        /// 判断两个经纬度的距离
        /// </summary>
        /// <param name="j1">第一个经度</param>
        /// <param name="w1">第一个纬度</param>
        /// <param name="j2">第二个经度</param>
        /// <param name="w2">第二个纬度</param>
        /// <returns></returns>
        public static double GetGreatCircleDistance(double j1, double w1, double j2, double w2)
        {
            LatLng start = new(j1, w1);
            LatLng end = new(j2, w2);

            double lat1 = (Math.PI / 180) * start.latitude;
            double lat2 = (Math.PI / 180) * end.latitude;

            double lon1 = (Math.PI / 180) * start.longitude;
            double lon2 = (Math.PI / 180) * end.longitude;

            double r = 6371000; //地球半径(米)

            double dd = Math.Acos(Math.Sin(lat1) * Math.Sin(lat2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(lon2 - lon1)) * r;
            return dd;
        }

        /// <summary>
        /// 获取随机数
        /// </summary>
        /// <param name="min">最小值 包含</param>
        /// <param name="max">最大值 不包含</param>
        /// <returns></returns>
        public static int GetRandom(int min, int max)
        {
            return rd.Next(min, max);
        }

        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public static long GetTimeStamp()
        {
            return (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
        }

        /// <summary>
        /// 获取请求IP
        /// </summary>
        public static string GetIp()
        {
            //return "127.0.0.1";//正式环境请注释
            IHttpContextAccessor _httpContextAccessor = new HttpContextAccessor();
            return _httpContextAccessor.HttpContext?.Connection.RemoteIpAddress?.ToString() ?? "127.0.0.1";
        }

        /// <summary>
        /// 有序的GUID（自定义规则）
        /// </summary>
        /// <returns></returns>
        public static string GUID()
        {
            byte[] bytes = Guid.NewGuid().ToByteArray();
            DateTime now = DateTime.UtcNow;

            bytes[3] = (byte)(now.Year - 2021); // 假设2021年为起点
            bytes[2] = (byte)now.Month;
            bytes[1] = (byte)now.Day;
            bytes[0] = (byte)now.Hour;
            Array.Copy(BitConverter.GetBytes(now.Millisecond), 0, bytes, 4, 2);
            Array.Copy(BitConverter.GetBytes(now.Second), 0, bytes, 6, 2);
            Array.Copy(Guid.NewGuid().ToByteArray(), 0, bytes, 8, 8);

            return new Guid(bytes).ToString().Replace("-", "");
        }

        /// <summary>
        /// 生成GUID（常规）
        /// </summary>
        /// <returns></returns>
        public static string GUID2()
        {
            return Guid.NewGuid().ToString().Replace("-", "").ToUpper();
        }

        // -------------------- 新增：订单ID生成方法 -------------------- 
        /// <summary>
        /// 生成订单ID（格式：P + yyMMdd + HHmmss + 4位当日流水号）
        /// </summary>
        /// <returns>订单ID字符串</returns>
        public static string GenerateOrderId()
        {
            // 1. 跨日重置流水号（线程安全）
            lock (typeof(Config)) // 锁保证多线程安全
            {
                if (DateTime.Today != _orderLastResetTime)
                {
                    _orderDailyCounter = 1;
                    _orderLastResetTime = DateTime.Today;
                }
            }

            // 2. 拼接各部分
            string prefix = "P";
            string datePart = DateTime.Now.ToString("yyMMdd"); // 如 240308
            string timePart = DateTime.Now.ToString("HHmmss"); // 如 083537
            string counterPart = _orderDailyCounter.ToString("D4"); // 补前导零，如 0001

            // 3. 累加流水号（线程安全）
            lock (typeof(Config))
            {
                _orderDailyCounter++;
            }

            // 4. 组合生成ID
            return $"{prefix}{datePart}{timePart}{counterPart}";
        }

        private static long _tIdDailyCounter = 1;
        private static DateTime _tIdLastResetTime = DateTime.Today;

        /// <summary>
        /// 生成 T 开头、15 位数字的业务 ID（格式：T + 15位数字，每日重置流水号）
        /// </summary>
        /// <returns>如 T638454518546184977 样式的字符串</returns>
        public static string GenerateTId()
        {
            lock (typeof(Config)) // 线程安全锁
            {
                // 跨日重置流水号
                if (DateTime.Today != _tIdLastResetTime)
                {
                    _tIdDailyCounter = 1;
                    _tIdLastResetTime = DateTime.Today;
                }

                // 拼接：前缀 T + 15位数字（日期编码 + 流水号补位）
                string prefix = "T";
                // 日期编码（yyMMdd + HHmmss 共 12 位，示例：240308152030）
                string dateCode = DateTime.Now.ToString("yyMMddHHmmss");
                // 流水号补 3 位（每日从 1 开始，最多 999，保证总长度 15 位）
                string counter = _tIdDailyCounter.ToString("D3");

                // 累加流水号
                _tIdDailyCounter++;

                // 组合：T + 日期编码(12位) + 流水号(3位) = 1+12+3=16？不，实际是 1（T） + 14（数字）？
                // 哦，你示例是 T + 15 位数字，重新调整：
                // 正确逻辑：固定 15 位数字，用时间戳+流水号生成，保证唯一
                // 改用更简单的方式：随机生成 15 位数字（但需保证不重复，这里用“日期+流水号”更稳妥）

                // 重新设计：15 位数字 = 时间戳(yyMMddHHmmss 是 12 位) + 3 位当日流水号
                string idNumber = $"{dateCode}{counter}";
                return $"{prefix}{idNumber}";
            }
        }

    }
}